package com.fecean.aabbc.commons.easy;

import org.jetbrains.annotations.Nullable;

import java.util.Collection;
import java.util.Map;
import java.util.function.Supplier;

/**
 * 断言类
 *
 * @author chenfenghai
 * @date 2019-12-11 15:46
 * @blame Android Team
 */
public class EasyAsserter {

    // Constructor.
    /**
     * private Constructor.
     */
    public EasyAsserter(){}


    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言true值
     * @param expression the expression to check
     * @throws IllegalArgumentException if expression is {@code false}
     * @see #isTrue(boolean, String, Object...)
     */
    public static void isTrue(final boolean expression){
        isTrue(expression, "The validated expression is false");
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言true值
     * @param expression the expression to check
     * @param message  the {@link String#format(String, Object...)} exception message if invalid, not null
     * @param values  the optional values for the formatted exception message, null array not recommended
     * @throws IllegalArgumentException if expression is {@code false}
     * @see #isTrue(boolean, Supplier)
     */
    public static void isTrue(final boolean expression, final String message, final Object... values){
        isTrue(expression, ()->new IllegalArgumentException(String.format(message, values)));
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言true值
     * @param expression the expression to check
     * @throws X if expression is {@code false}
     */
    public static <X extends Throwable> void isTrue(final boolean expression, Supplier<? extends X> exceptionSupplier) throws X {
        if(!expression){
            throw exceptionSupplier.get();
        }
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotNull值
     * @param object the object to check
     * @throws NullPointerException if object is {@code null}
     * @see #notNull(Object, String, Object...)
     */
    public static <T> T notNull(@Nullable final T object){
        return notNull(object, "The validated object is null");
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotNull值
     * @param object the object to check
     * @param message  the {@link String#format(String, Object...)} exception message if invalid, not null
     * @param values  the optional values for the formatted exception message, null array not recommended
     * @throws NullPointerException if expression is {@code null}
     * @see #notNull(Object, Supplier)
     */
    public static <T> T notNull(@Nullable final T object, final String message, final Object... values){
        return notNull(object, () -> new NullPointerException(String.format(message, values)));
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotNull值
     * @param object the expression to check
     * @throws X if expression is {@code null}
     */
    public static <T, X extends Throwable> T notNull(@Nullable final T object, Supplier<? extends X> exceptionSupplier) throws X {
        if(object == null){
            throw exceptionSupplier.get();
        }
        return object;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotEmpty值
     * @param chars the chars to check
     * @throws IllegalArgumentException if chars is empty
     * @see #notEmpty(CharSequence, String, Object...)
     * @see EasyValidator#isEmpty(CharSequence)
     */
    public static <T extends CharSequence> T notEmpty(@Nullable final T chars){
        return notEmpty(chars, "The validated chars is empty");
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotEmpty值
     * @param chars the chars to check
     * @param message  the {@link String#format(String, Object...)} exception message if invalid, not null
     * @param values  the optional values for the formatted exception message, null array not recommended
     * @throws IllegalArgumentException if chars is empty
     * @see #notEmpty(CharSequence, Supplier)
     * @see EasyValidator#isEmpty(CharSequence)
     */
    public static <T extends CharSequence> T notEmpty(@Nullable final T chars, final String message, final Object... values){
        return notEmpty(chars, () -> new IllegalArgumentException(String.format(message, values)));
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotEmpty值
     * @param chars the chars to check
     * @throws X if chars is empty
     * @see EasyValidator#isEmpty(CharSequence)
     */
    public static <T extends CharSequence, X extends Throwable> T notEmpty(@Nullable final T chars, Supplier<? extends X> exceptionSupplier) throws X {
        if(EasyValidator.isEmpty(chars)){
            throw exceptionSupplier.get();
        }
        return chars;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotEmpty值
     * @param collection the collection to check
     * @throws IllegalArgumentException if collection is empty
     * @see #notEmpty(Collection, String, Object...)
     * @see EasyValidator#isEmpty(Collection)
     */
    public static <T extends Collection<?>> T notEmpty(@Nullable final T collection){
        return notEmpty(collection, "The validated collection is empty");
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotEmpty值
     * @param collection the collection to check
     * @param message  the {@link String#format(String, Object...)} exception message if invalid, not null
     * @param values  the optional values for the formatted exception message, null array not recommended
     * @throws IllegalArgumentException if collection is empty
     * @see #notEmpty(Collection, Supplier)
     * @see EasyValidator#isEmpty(Collection)
     */
    public static <T extends Collection<?>> T notEmpty(@Nullable final T collection, final String message, final Object... values){
        return notEmpty(collection, () -> new IllegalArgumentException(String.format(message, values)));
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotEmpty值
     * @param collection the collection to check
     * @throws X if collection is empty
     * @see EasyValidator#isEmpty(Collection)
     */
    public static <T extends Collection<?>, X extends Throwable> T notEmpty(@Nullable final T collection, Supplier<? extends X> exceptionSupplier) throws X {
        if(EasyValidator.isEmpty(collection)){
            throw exceptionSupplier.get();
        }
        return collection;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotEmpty值
     * @param map the map to check
     * @throws IllegalArgumentException if map is empty
     * @see #notEmpty(Map, String, Object...)
     * @see EasyValidator#isEmpty(Map)
     */
    public static <T extends Map<?, ?>> T notEmpty(@Nullable final T map){
        return notEmpty(map, "The validated map is empty");
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotEmpty值
     * @param map the map to check
     * @param message  the {@link String#format(String, Object...)} exception message if invalid, not null
     * @param values  the optional values for the formatted exception message, null array not recommended
     * @throws IllegalArgumentException if map is empty
     * @see #notEmpty(Map, Supplier)
     * @see EasyValidator#isEmpty(Map)
     */
    public static <T extends Map<?, ?>> T notEmpty(@Nullable final T map, final String message, final Object... values){
        return notEmpty(map, () -> new IllegalArgumentException(String.format(message, values)));
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotEmpty值
     * @param map the map to check
     * @throws X if map is empty
     * @see EasyValidator#isEmpty(Map)
     */
    public static <T extends Map<?, ?>, X extends Throwable> T notEmpty(@Nullable final T map, Supplier<? extends X> exceptionSupplier) throws X {
        if(EasyValidator.isEmpty(map)){
            throw exceptionSupplier.get();
        }
        return map;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotEmpty值
     * @param array the array to check
     * @throws IllegalArgumentException if array is empty
     * @see #notEmpty(Object[], String, Object...)
     * @see EasyValidator#notEmpty(Object[])
     */
    public static <T> T[] notEmpty(@Nullable final T[] array){
        return notEmpty(array, "The validated array is empty");
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotEmpty值
     * @param array the array to check
     * @param message  the {@link String#format(String, Object...)} exception message if invalid, not null
     * @param values  the optional values for the formatted exception message, null array not recommended
     * @throws IllegalArgumentException if array is empty
     * @see #notEmpty(Object[], Supplier)
     * @see EasyValidator#isEmpty(Object[])
     */
    public static <T> T[] notEmpty(@Nullable final T[] array, final String message, final Object... values){
        return notEmpty(array, () -> new IllegalArgumentException(String.format(message, values)));
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotEmpty值
     * @param array the array to check
     * @throws X if object is empty
     * @see EasyValidator#isEmpty(Object[])
     */
    public static <T, X extends Throwable> T[] notEmpty(@Nullable final T[] array, Supplier<? extends X> exceptionSupplier) throws X {
        if(EasyValidator.isEmpty(array)){
            throw exceptionSupplier.get();
        }
        return array;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotEmpty值
     * @param object the object to check
     * @throws IllegalArgumentException if object is empty
     * @see #notEmpty(Object, String, Object...)
     * @see EasyValidator#isEmpty(Object)
     */
    public static <T> T notEmpty(@Nullable final T object){
        return notEmpty(object, "The validated object is empty");
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotEmpty值
     * @param object the object to check
     * @param message  the {@link String#format(String, Object...)} exception message if invalid, not null
     * @param values  the optional values for the formatted exception message, null array not recommended
     * @throws IllegalArgumentException if object is empty
     * @see #notEmpty(Object, Supplier)
     * @see EasyValidator#isEmpty(Object)
     */
    public static <T> T notEmpty(@Nullable final T object, final String message, final Object... values){
        return notEmpty(object, () -> new IllegalArgumentException(String.format(message, values)));
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotEmpty值
     * @param object the object to check
     * @throws X if object is empty
     * @see EasyValidator#isEmpty(Object)
     */
    public static <T, X extends Throwable> T notEmpty(@Nullable final T object, Supplier<? extends X> exceptionSupplier) throws X {
        if(EasyValidator.isEmpty(object)){
            throw exceptionSupplier.get();
        }
        return object;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotBlank值
     * @param chars the chars to check
     * @throws IllegalArgumentException if chars is blank
     * @see #notBlank(CharSequence, String, Object...)
     * @see EasyValidator#isBlank(CharSequence)
     */
    public static <T extends CharSequence> T notBlank(@Nullable final T chars){
        return notBlank(chars, "The validated character sequence is blank");
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotBlank值
     * @param chars the chars to check
     * @param message  the {@link String#format(String, Object...)} exception message if invalid, not null
     * @param values  the optional values for the formatted exception message, null array not recommended
     * @throws IllegalArgumentException if chars is blank
     * @see #notBlank(CharSequence, Supplier)
     * @see EasyValidator#isBlank(CharSequence)
     */
    public static <T extends CharSequence> T notBlank(@Nullable final T chars, final String message, final Object... values){
        return notBlank(chars, () -> new IllegalArgumentException(String.format(message, values)));
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotBlank值
     * @param chars the chars to check
     * @throws X if chars is blank
     * @see EasyValidator#isBlank(CharSequence)
     */
    public static <T extends CharSequence, X extends Throwable> T notBlank(@Nullable final T chars, Supplier<? extends X> exceptionSupplier) throws X {
        if(EasyValidator.isBlank(chars)){
            throw exceptionSupplier.get();
        }
        return chars;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotBlank值
     * @param object the object to check
     * @throws IllegalArgumentException if object is blank
     * @see #notBlank(Object, String, Object...)
     * @see EasyValidator#isBlank(Object)
     */
    public static <T> T notBlank(@Nullable final T object){
        return notBlank(object, "The validated object is blank");
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotBlank值
     * @param object the object to check
     * @param message  the {@link String#format(String, Object...)} exception message if invalid, not null
     * @param values  the optional values for the formatted exception message, null array not recommended
     * @throws IllegalArgumentException if object is blank
     * @see #notBlank(Object, Supplier)
     * @see EasyValidator#isBlank(Object)
     */
    public static <T> T notBlank(@Nullable final T object, final String message, final Object... values){
        return notBlank(object, () -> new IllegalArgumentException(String.format(message, values)));
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言NotBlank值
     * @param object the object to check
     * @throws X if object is blank
     * @see EasyValidator#isBlank(Object)
     */
    public static <T, X extends Throwable> T notBlank(@Nullable final T object, Supplier<? extends X> exceptionSupplier) throws X {
        if(EasyValidator.isBlank(object)){
            throw exceptionSupplier.get();
        }
        return object;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否日期格式：yyyy-MM-dd
     * @param chars the chars to check
     * @throws IllegalArgumentException if object does not match yyyy-MM-dd
     * @see #isDate(CharSequence, String, Object...)
     * @see EasyValidator#isDate(CharSequence)
     */
    public static <T extends CharSequence> T isDate(@Nullable final T chars){
        return isDate(chars, "The validated chars [%s] does not match yyyy-MM-dd", chars);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否日期格式：yyyy-MM-dd
     * @param chars the chars to check
     * @param message  the {@link String#format(String, Object...)} exception message if invalid, not null
     * @param values  the optional values for the formatted exception message, null array not recommended
     * @throws IllegalArgumentException if object does not match yyyy-MM-dd
     * @see #isDate(CharSequence, Supplier)
     * @see EasyValidator#isDate(CharSequence)
     */
    public static <T extends CharSequence> T isDate(@Nullable final T chars, final String message, final Object... values){
        return isDate(chars, () -> new IllegalArgumentException(String.format(message, values)));
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否日期格式：yyyy-MM-dd
     * @param chars the chars to check
     * @throws X if object does not match yyyy-MM-dd
     * @see EasyValidator#isDate(CharSequence)
     */
    public static <T extends CharSequence, X extends Throwable> T isDate(@Nullable final T chars, Supplier<? extends X> exceptionSupplier) throws X {
        if(!EasyValidator.isDate(chars)){
            throw exceptionSupplier.get();
        }
        return chars;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否日期格式：yyyy-MM-dd
     * @param object the object to check
     * @throws IllegalArgumentException if object does not match yyyy-MM-dd
     * @see #isDate(Object, String, Object...)
     * @see EasyValidator#isDate(Object)
     */
    public static <T> T isDate(@Nullable final T object){
        return isDate(object, "The validated object [%s] does not match yyyy-MM-dd", object);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否日期格式：yyyy-MM-dd
     * @param object the object to check
     * @param message  the {@link String#format(String, Object...)} exception message if invalid, not null
     * @param values  the optional values for the formatted exception message, null array not recommended
     * @throws IllegalArgumentException if object does not match yyyy-MM-dd
     * @see #isDate(Object, Supplier)
     * @see EasyValidator#isDate(Object)
     */
    public static <T> T isDate(@Nullable final T object, final String message, final Object... values){
        return isDate(object, () -> new IllegalArgumentException(String.format(message, values)));
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否日期格式：yyyy-MM-dd
     * @param object the object to check
     * @throws X if object does not match yyyy-MM-dd
     * @see EasyValidator#isDate(Object)
     */
    public static <T, X extends Throwable> T isDate(@Nullable final T object, Supplier<? extends X> exceptionSupplier) throws X {
        if(!EasyValidator.isDate(object)){
            throw exceptionSupplier.get();
        }
        return object;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否日期时间格式：yyyy-MM-dd HH:mm:ss
     * @param chars the chars to check
     * @throws IllegalArgumentException if object does not match yyyy-MM-dd HH:mm:ss
     * @see #isDateTime(CharSequence, String, Object...)
     * @see EasyValidator#isDateTime(CharSequence)
     */
    public static <T extends CharSequence> T isDateTime(@Nullable final T chars){
        return isDateTime(chars, "The validated chars [%s] does not match yyyy-MM-dd HH:mm:ss", chars);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否日期时间格式：yyyy-MM-dd HH:mm:ss
     * @param chars the chars to check
     * @param message  the {@link String#format(String, Object...)} exception message if invalid, not null
     * @param values  the optional values for the formatted exception message, null array not recommended
     * @throws IllegalArgumentException if object does not match yyyy-MM-dd HH:mm:ss
     * @see #isDateTime(CharSequence, Supplier)
     * @see EasyValidator#isDateTime(CharSequence)
     */
    public static <T extends CharSequence> T isDateTime(@Nullable final T chars, final String message, final Object... values){
        return isDateTime(chars, () -> new IllegalArgumentException(String.format(message, values)));
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否日期时间格式：yyyy-MM-dd HH:mm:ss
     * @param chars the chars to check
     * @throws X if object does not match yyyy-MM-dd HH:mm:ss
     * @see EasyValidator#isDateTime(CharSequence)
     */
    public static <T extends CharSequence, X extends Throwable> T isDateTime(@Nullable final T chars, Supplier<? extends X> exceptionSupplier) throws X {
        if(!EasyValidator.isDateTime(chars)){
            throw exceptionSupplier.get();
        }
        return chars;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否日期时间格式：yyyy-MM-dd HH:mm:ss
     * @param object the object to check
     * @throws IllegalArgumentException if object does not match yyyy-MM-dd HH:mm:ss
     * @see #isDateTime(Object, String, Object...)
     * @see EasyValidator#isDateTime(Object)
     */
    public static <T> T isDateTime(@Nullable final T object){
        return isDateTime(object, "The validated object [%s] does not match yyyy-MM-dd HH:mm:ss", object);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否日期时间格式：yyyy-MM-dd HH:mm:ss
     * @param object the object to check
     * @param message  the {@link String#format(String, Object...)} exception message if invalid, not null
     * @param values  the optional values for the formatted exception message, null array not recommended
     * @throws IllegalArgumentException if object does not match yyyy-MM-dd HH:mm:ss
     * @see #isDateTime(Object, Supplier)
     * @see EasyValidator#isDateTime(Object)
     */
    public static <T> T isDateTime(@Nullable final T object, final String message, final Object... values){
        return isDateTime(object, () -> new IllegalArgumentException(String.format(message, values)));
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否日期时间格式：yyyy-MM-dd HH:mm:ss
     * @param object the object to check
     * @throws X if object does not match yyyy-MM-dd HH:mm:ss
     * @see EasyValidator#isDateTime(Object)
     */
    public static <T, X extends Throwable> T isDateTime(@Nullable final T object, Supplier<? extends X> exceptionSupplier) throws X {
        if(!EasyValidator.isDateTime(object)){
            throw exceptionSupplier.get();
        }
        return object;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否匹配指定日期格式
     * @param <T> the object type
     * @param chars the chars to check
     * @param pattern the datetime format. for example: yyyy-MM-dd HH:mm:ss
     * @throws IllegalArgumentException if the chars does not match the pattern
     * @see #isDateTimeFormat(CharSequence, String, String, Object...)
     * @see EasyValidator#isDateTimeFormat(CharSequence, String)
     */
    public static <T extends CharSequence> T isDateTimeFormat(@Nullable final T chars, @Nullable String pattern){
        return isDateTimeFormat(chars, pattern, "The validated chars [%s] does not match the pattern [%s]", chars, pattern);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否匹配指定日期格式
     * @param <T> the object type
     * @param chars the chars to check
     * @param pattern the datetime format. for example: yyyy-MM-dd HH:mm:ss
     * @param message  the {@link String#format(String, Object...)} exception message if invalid, not null
     * @param values  the optional values for the formatted exception message, null array not recommended
     * @throws IllegalArgumentException if the chars does not match the pattern
     * @see #isDateTimeFormat(CharSequence, String, Supplier)
     * @see EasyValidator#isDateTimeFormat(CharSequence, String)
     */
    public static <T extends CharSequence> T isDateTimeFormat(@Nullable final T chars, @Nullable String pattern, final String message, final Object... values){
        return isDateTimeFormat(chars, pattern, () -> new IllegalArgumentException(String.format(message, values)));
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否匹配指定日期格式
     * @param <T> the object type
     * @param chars the chars to check
     * @param pattern the datetime format. for example: yyyy-MM-dd HH:mm:ss
     * @throws X if the chars does not match the pattern
     * @see EasyValidator#isDateTimeFormat(CharSequence, String)
     */
    public static <T extends CharSequence, X extends Throwable> T isDateTimeFormat(@Nullable final T chars, @Nullable String pattern, Supplier<? extends X> exceptionSupplier) throws X {
        if(!EasyValidator.isDateTimeFormat(chars, pattern)){
            throw exceptionSupplier.get();
        }
        return chars;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否匹配指定日期格式
     * @param <T> the object type
     * @param object the object to check
     * @param pattern the datetime format. for example: yyyy-MM-dd HH:mm:ss
     * @throws IllegalArgumentException if the object does not match the pattern
     * @see #isDateTimeFormat(Object, String, String, Object...)
     * @see EasyValidator#isDateTimeFormat(Object, String)
     */
    public static <T> T isDateTimeFormat(@Nullable final T object, @Nullable String pattern){
        return isDateTimeFormat(object, pattern, "The validated object [%s] does not match the pattern [%s]", object, pattern);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否匹配指定日期格式
     * @param <T> the object type
     * @param object the object to check
     * @param pattern the datetime format. for example: yyyy-MM-dd HH:mm:ss
     * @param message  the {@link String#format(String, Object...)} exception message if invalid, not null
     * @param values  the optional values for the formatted exception message, null array not recommended
     * @throws IllegalArgumentException if the object does not match the pattern
     * @see #isDateTimeFormat(Object, String, Supplier)
     * @see EasyValidator#isDateTimeFormat(Object, String)
     */
    public static <T> T isDateTimeFormat(@Nullable final T object, @Nullable String pattern, final String message, final Object... values){
        return isDateTimeFormat(object, pattern, () -> new IllegalArgumentException(String.format(message, values)));
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否匹配指定日期格式
     * @param <T> the object type
     * @param object the object to check
     * @param pattern the datetime format. for example: yyyy-MM-dd HH:mm:ss
     * @throws X if the object does not match the pattern
     * @see EasyValidator#isDateTimeFormat(Object, String)
     */
    public static <T, X extends Throwable> T isDateTimeFormat(@Nullable final T object, @Nullable String pattern, Supplier<? extends X> exceptionSupplier) throws X {
        if(!EasyValidator.isDateTimeFormat(object, pattern)){
            throw exceptionSupplier.get();
        }
        return object;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否匹配正则表达式
     * @param <T> the object type
     * @param regex The expression to be compiled
     * @param chars The chars sequence to be matched
     * @throws IllegalArgumentException if the chars does not match the regex
     * @see #isMatch(String, Object, String, Object...)
     * @see EasyValidator#isMatch(String, CharSequence)
     */
    public static <T extends CharSequence> T isMatch(@Nullable String regex, @Nullable final T chars){
        return isMatch(regex, chars, "The validated chars [%s] does not match the regex [%s]", chars, regex);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否匹配正则表达式
     * @param <T> the object type
     * @param regex The expression to be compiled
     * @param chars The chars sequence to be matched
     * @param message  the {@link String#format(String, Object...)} exception message if invalid, not null
     * @param values  the optional values for the formatted exception message, null array not recommended
     * @throws IllegalArgumentException if the chars does not match the regex
     * @see #isMatch(String, Object, Supplier)
     * @see EasyValidator#isMatch(String, CharSequence)
     */
    public static <T extends CharSequence> T isMatch(@Nullable String regex, @Nullable final T chars, final String message, final Object... values){
        return isMatch(regex, chars, () -> new IllegalArgumentException(String.format(message, values)));
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否匹配正则表达式
     * @param <T> the object type
     * @param regex The expression to be compiled
     * @param chars The chars sequence to be matched
     * @throws X if the chars does not match the regex
     * @see EasyValidator#isMatch(String, CharSequence)
     */
    public static <T extends CharSequence, X extends Throwable> T isMatch(@Nullable String regex, @Nullable final T chars, Supplier<? extends X> exceptionSupplier) throws X {
        if(!EasyValidator.isMatch(regex, chars)){
            throw exceptionSupplier.get();
        }
        return chars;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否匹配正则表达式
     * @param <T> the object type
     * @param regex The expression to be compiled
     * @param object The object sequence to be matched
     * @throws IllegalArgumentException if the object does not match the regex
     * @see #isMatch(String, Object, String, Object...)
     * @see EasyValidator#isMatch(String, Object)
     */
    public static <T> T isMatch(@Nullable String regex, @Nullable final T object){
        return isMatch(regex, object, "The validated object [%s] does not match the regex [%s]", object, regex);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否匹配正则表达式
     * @param <T> the object type
     * @param regex The expression to be compiled
     * @param object The object sequence to be matched
     * @param message  the {@link String#format(String, Object...)} exception message if invalid, not null
     * @param values  the optional values for the formatted exception message, null array not recommended
     * @throws IllegalArgumentException if the object does not match the regex
     * @see #isMatch(String, Object, Supplier)
     * @see EasyValidator#isMatch(String, Object)
     */
    public static <T> T isMatch(@Nullable String regex, @Nullable final T object, final String message, final Object... values){
        return isMatch(regex, object, () -> new IllegalArgumentException(String.format(message, values)));
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 断言字符串是否匹配正则表达式
     * @param <T> the object type
     * @param regex The expression to be compiled
     * @param object The object sequence to be matched
     * @throws X if the object does not match the regex
     * @see EasyValidator#isMatch(String, Object)
     */
    public static <T, X extends Throwable> T isMatch(@Nullable String regex, @Nullable final T object, Supplier<? extends X> exceptionSupplier) throws X {
        if(!EasyValidator.isMatch(regex, object)){
            throw exceptionSupplier.get();
        }
        return object;
    }
}
